//! 复合索引测试
//! 
//! 测试复合索引的核心功能

#[cfg(test)]
mod tests {
    use super::super::composite::*;
    use crate::sql::Value;

    #[test]
    fn test_composite_btree_basic_operations() {
        let mut index = CompositeIndex::new(
            "test_index".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::BTree,
        ).unwrap();
        
        // 测试插入
        assert!(index.insert(vec![Value::Integer(1), Value::Text("a".to_string())], 1).is_ok());
        assert!(index.insert(vec![Value::Integer(2), Value::Text("b".to_string())], 2).is_ok());
        assert!(index.insert(vec![Value::Integer(1), Value::Text("b".to_string())], 3).is_ok());
        
        // 测试查找
        assert_eq!(
            index.lookup(vec![Value::Integer(1), Value::Text("a".to_string())]).unwrap(),
            Some(1)
        );
        assert_eq!(
            index.lookup(vec![Value::Integer(2), Value::Text("b".to_string())]).unwrap(),
            Some(2)
        );
        assert_eq!(
            index.lookup(vec![Value::Integer(1), Value::Text("b".to_string())]).unwrap(),
            Some(3)
        );
        assert_eq!(
            index.lookup(vec![Value::Integer(3), Value::Text("c".to_string())]).unwrap(),
            None
        );
    }
    
    #[test]
    fn test_composite_hash_basic_operations() {
        let mut index = CompositeIndex::new(
            "test_hash_index".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::Hash,
        ).unwrap();
        
        // 测试插入
        assert!(index.insert(vec![Value::Integer(1), Value::Text("a".to_string())], 1).is_ok());
        assert!(index.insert(vec![Value::Integer(2), Value::Text("b".to_string())], 2).is_ok());
        
        // 测试查找
        assert_eq!(
            index.lookup(vec![Value::Integer(1), Value::Text("a".to_string())]).unwrap(),
            Some(1)
        );
        assert_eq!(
            index.lookup(vec![Value::Integer(2), Value::Text("b".to_string())]).unwrap(),
            Some(2)
        );
        assert_eq!(
            index.lookup(vec![Value::Integer(3), Value::Text("c".to_string())]).unwrap(),
            None
        );
    }
    
    #[test]
    fn test_composite_prefix_lookup() {
        let mut index = CompositeIndex::new(
            "test_prefix".to_string(),
            vec!["col1".to_string(), "col2".to_string(), "col3".to_string()],
            CompositeIndexType::BTree,
        ).unwrap();
        
        // 插入测试数据
        index.insert(vec![Value::Integer(1), Value::Text("a".to_string()), Value::Integer(10)], 1).unwrap();
        index.insert(vec![Value::Integer(1), Value::Text("a".to_string()), Value::Integer(20)], 2).unwrap();
        index.insert(vec![Value::Integer(1), Value::Text("b".to_string()), Value::Integer(30)], 3).unwrap();
        index.insert(vec![Value::Integer(2), Value::Text("a".to_string()), Value::Integer(40)], 4).unwrap();
        
        // 测试前缀查找
        let results = index.prefix_lookup(vec![Value::Integer(1)]).unwrap();
        assert_eq!(results.len(), 3); // 应该找到3条记录
        assert!(results.contains(&1));
        assert!(results.contains(&2));
        assert!(results.contains(&3));
        
        let results = index.prefix_lookup(vec![Value::Integer(1), Value::Text("a".to_string())]).unwrap();
        assert_eq!(results.len(), 2); // 应该找到2条记录
        assert!(results.contains(&1));
        assert!(results.contains(&2));
    }
    
    #[test]
    fn test_composite_range_lookup() {
        let mut index = CompositeIndex::new(
            "test_range".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::BTree,
        ).unwrap();
        
        // 插入测试数据
        for i in 1..=10 {
            for j in 1..=5 {
                index.insert(
                    vec![Value::Integer(i), Value::Integer(j)],
                    (i * 10 + j) as usize
                ).unwrap();
            }
        }
        
        // 测试范围查找
        let results = index.range_lookup(
            vec![Value::Integer(3), Value::Integer(2)],
            vec![Value::Integer(5), Value::Integer(4)]
        ).unwrap();
        
        // 验证结果
        assert!(!results.is_empty());
        for &row_id in &results {
            let i = row_id / 10;
            let j = row_id % 10;
            assert!(i >= 3 && i <= 5);
            if i == 3 {
                assert!(j >= 2);
            }
            if i == 5 {
                assert!(j <= 4);
            }
        }
    }
    
    #[test]
    fn test_composite_hash_no_range_support() {
        let mut index = CompositeIndex::new(
            "test_hash_no_range".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::Hash,
        ).unwrap();
        
        // 哈希索引不支持范围查询
        let result = index.range_lookup(
            vec![Value::Integer(1), Value::Integer(1)],
            vec![Value::Integer(2), Value::Integer(2)]
        );
        assert!(result.is_err());
        
        // 哈希索引不支持前缀查询
        let result = index.prefix_lookup(vec![Value::Integer(1)]);
        assert!(result.is_err());
    }
    
    #[test]
    fn test_composite_key_validation() {
        let mut index = CompositeIndex::new(
            "test_validation".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::BTree,
        ).unwrap();
        
        // 测试键长度不匹配
        let result = index.insert(vec![Value::Integer(1)], 1);
        assert!(result.is_err());
        
        let result = index.insert(
            vec![Value::Integer(1), Value::Text("a".to_string()), Value::Integer(2)],
            1
        );
        assert!(result.is_err());
        
        let result = index.lookup(vec![Value::Integer(1)]);
        assert!(result.is_err());
    }
    
    #[test]
    fn test_composite_delete() {
        let mut index = CompositeIndex::new(
            "test_delete".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::BTree,
        ).unwrap();
        
        // 插入数据
        index.insert(vec![Value::Integer(1), Value::Text("a".to_string())], 1).unwrap();
        index.insert(vec![Value::Integer(2), Value::Text("b".to_string())], 2).unwrap();
        
        // 验证数据存在
        assert_eq!(
            index.lookup(vec![Value::Integer(1), Value::Text("a".to_string())]).unwrap(),
            Some(1)
        );
        
        // 删除数据
        index.delete(vec![Value::Integer(1), Value::Text("a".to_string())]).unwrap();
        
        // 验证数据已删除
        assert_eq!(
            index.lookup(vec![Value::Integer(1), Value::Text("a".to_string())]).unwrap(),
            None
        );
        assert_eq!(
            index.lookup(vec![Value::Integer(2), Value::Text("b".to_string())]).unwrap(),
            Some(2)
        );
    }
    
    #[test]
    fn test_composite_statistics() {
        let mut index = CompositeIndex::new(
            "test_stats".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::BTree,
        ).unwrap();
        
        // 插入数据
        for i in 1..=10 {
            index.insert(vec![Value::Integer(i), Value::Text(format!("val{}", i))], i as usize).unwrap();
        }
        
        // 执行一些查找
        for i in 1..=5 {
            index.lookup(vec![Value::Integer(i), Value::Text(format!("val{}", i))]).unwrap();
        }
        
        // 执行前缀查找
        index.prefix_lookup(vec![Value::Integer(1)]).unwrap();
        
        let stats = index.get_stats();
        assert_eq!(stats.total_entries, 10);
        assert_eq!(stats.insert_count, 10);
        assert_eq!(stats.lookup_count, 5);
        assert_eq!(stats.prefix_query_count, 1);
    }
    
    #[test]
    fn test_composite_performance() {
        let mut btree_index = CompositeIndex::new(
            "perf_btree".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::BTree,
        ).unwrap();
        
        let mut hash_index = CompositeIndex::new(
            "perf_hash".to_string(),
            vec!["col1".to_string(), "col2".to_string()],
            CompositeIndexType::Hash,
        ).unwrap();
        
        let n = 1000;
        
        // 测试B+树插入性能
        let start = std::time::Instant::now();
        for i in 0..n {
            btree_index.insert(
                vec![Value::Integer(i), Value::Text(format!("val{}", i))],
                i as usize
            ).unwrap();
        }
        let btree_insert_time = start.elapsed();
        
        // 测试哈希索引插入性能
        let start = std::time::Instant::now();
        for i in 0..n {
            hash_index.insert(
                vec![Value::Integer(i), Value::Text(format!("val{}", i))],
                i as usize
            ).unwrap();
        }
        let hash_insert_time = start.elapsed();
        
        // 测试B+树查找性能
        let start = std::time::Instant::now();
        for i in 0..n {
            btree_index.lookup(vec![Value::Integer(i), Value::Text(format!("val{}", i))]).unwrap();
        }
        let btree_lookup_time = start.elapsed();
        
        // 测试哈希索引查找性能
        let start = std::time::Instant::now();
        for i in 0..n {
            hash_index.lookup(vec![Value::Integer(i), Value::Text(format!("val{}", i))]).unwrap();
        }
        let hash_lookup_time = start.elapsed();
        
        println!("复合索引性能测试 ({}条记录):", n);
        println!("B+树插入时间: {:?}", btree_insert_time);
        println!("哈希插入时间: {:?}", hash_insert_time);
        println!("B+树查找时间: {:?}", btree_lookup_time);
        println!("哈希查找时间: {:?}", hash_lookup_time);
        
        // 性能要求
        assert!(btree_insert_time.as_millis() < 1000);
        assert!(hash_insert_time.as_millis() < 500);
        assert!(btree_lookup_time.as_millis() < 500);
        assert!(hash_lookup_time.as_millis() < 200);
    }
    
    #[test]
    fn test_composite_key_operations() {
        let key1 = CompositeKey::new(vec![
            Value::Integer(1),
            Value::Text("test".to_string()),
            Value::Boolean(true)
        ]);
        
        assert_eq!(key1.len(), 3);
        assert!(!key1.is_empty());
        assert_eq!(key1.get(0), Some(&Value::Integer(1)));
        assert_eq!(key1.get(1), Some(&Value::Text("test".to_string())));
        assert_eq!(key1.get(2), Some(&Value::Boolean(true)));
        assert_eq!(key1.get(3), None);
        
        // 测试前缀
        let prefix = key1.prefix(2);
        assert_eq!(prefix.len(), 2);
        assert_eq!(prefix.get(0), Some(&Value::Integer(1)));
        assert_eq!(prefix.get(1), Some(&Value::Text("test".to_string())));
    }
}
